package com.seanzx.dp.serializer.impl;

import com.seanzx.dp.entity.Column;
import com.seanzx.dp.serializer.ISerializer;

import java.io.FilterInputStream;
import java.io.IOException;

/**
 * TINTINT/BIT/BOOL/BOOLEAN: lower endian, read next 1 byte as a number, from -128 to 127.
 * SMALLINT: lower endian, read next 2 bytes as a number. from -32768 to 32767.
 * MEDIUMINT: lower endian, read next 3 bytes as a number. from -8388608 to 8388607
 * INT: lower endian, read next 4 bytes as a number. from -2147483648 to 2147483647
 * BIGINT: lower endian, read next 8 bytes as a number. from -9223372036854775808 to 9223372036854775807
 */
public class NumberSerializer implements ISerializer {
    private final int length;

    public NumberSerializer(int length) {
        this.length = length;
    }

    @Override
    public String deserialize(Column column, FilterInputStream inputStream) throws IOException {
        byte[] bytes = new byte[length];
        inputStream.read(bytes);
        long result = 0;
        boolean negate = (bytes[bytes.length - 1] & 0x80) == 0x80;
        if (negate) {
            for (int i = 0; i < bytes.length; i++) {
                result += (long) (0xFF - (bytes[i] & 0xFF)) << 8 * i;
            }
            result = result * -1 - 1;
        } else {
            for (int i = 0; i < bytes.length; i++) {
                result += (long) (bytes[i] & 0xFF) << (i * 8);
            }
        }
        return String.valueOf(result);
    }

    @Override
    public byte[] serialize(Column column, String value) {
        long val = Long.parseLong(value);
        byte[] bytes = new byte[length];
        if (val < 0) {
            val = val * -1 - 1;
            for (int i = 0; i < bytes.length; i++) {
                long byteMod = 1L << (i + 1) * 8;
                bytes[i] = (byte) (0xFF - val % byteMod);
                val /= byteMod;
            }
        } else {
            int i = 0;
            while (val > 0) {
                bytes[i] = (byte) (val % 0xFF);
                val /= 0xFF;
            }
        }
        return bytes;
    }

    public static void main(String[] args) {
        long val = Long.parseLong("0");
        byte[] bytes = new byte[3];
        if (val < 0) {
            val = val * -1 - 1;
            for (int i = 0; i < bytes.length; i++) {
                bytes[i] = (byte) (0xFF - val % (1 << (i + 1) * 8));
                val /= 1 << (i + 1) * 8;
            }
        } else {
            int i = 0;
            while (val > 0) {
                bytes[i] = (byte) (val % 0xFF);
                val /= 0xFF;
            }
        }

        long result = 0;
        boolean negate = (bytes[bytes.length - 1] & 0x80) == 0x80;
        if (negate) {
            for (int i = 0; i < bytes.length; i++) {
                result += (long) (0xFF - (bytes[i] & 0xFF)) << 8 * i;
            }
            result = result * -1 - 1;
        } else {
            for (int i = 0; i < bytes.length; i++) {
                result += (long) (bytes[i] & 0xFF) << (i * 8);
            }
        }
        System.out.println(result);
    }
}
